使用Hadoop分析气象数据完整版(附带完整代码) 您所在的位置:网站首页 hadoop 数据结构 使用Hadoop分析气象数据完整版(附带完整代码)

使用Hadoop分析气象数据完整版(附带完整代码)

2024-07-07 05:52| 来源: 网络整理| 查看: 265

《分布式》布置了一道小作业,让我花了7天时间学习了Hadoop。。。现在终于可以正式地做这个作业了,记录一下。

使用Hadoop分析气象数据 1 获取数据1.1 下载数据1.2 数据格式1.3 合并数据 2 MapReduce处理数据2.1 环境配置,启动集群2.2 上传到HDFS2.2 编写MapReduce代码2.2.1 TemperatureMapper2.2.2 TemperatureReducer2.2.3 JobMain 2.3 执行2.3.1 打包、上传2.3.2 运行 3 导入数据到Hive4 Hive数据分析5 使用Sqoop导入数据到Mysql5.1 Mysql创建数据库5.2 开始导入 6 展示数据6.1 前端代码6.2 后端代码

1 获取数据 1.1 下载数据

注意:为了不出现横向拖拉,命令里我加了换行,所有命令都是如此。 获取命令:

wget -D --accept-regex=REGEX -P data -r -c ftp://ftp.ncdc.noaa.gov/pub/data/noaa/isd-lite/2019/5*

注意:下载可能出现卡顿,直接 ctrl+c 中断,然后再次输入命令即可。

我就下载了下面这么多,共计78429条。 在这里插入图片描述

1.2 数据格式

截取部分数据,格式如下:

2019 01 01 00 -65 -123 10199 345 95 8 -9999 -9999 2019 01 01 01 -62 -115 10213 350 86 -9999 -9999 -9999 2019 01 01 02 -62 -110 10223 343 86 -9999 -9999 -9999 2019 01 01 03 -62 -114 10234 337 77 -9999 -9999 -9999 2019 01 01 04 -62 -118 10242 345 86 -9999 -9999 -9999 2019 01 01 05 -62 -116 10252 331 63 -9999 -9999 -9999 2019 01 01 06 -62 -114 10259 306 38 6 -9999 -9999 2019 01 01 07 -62 -114 10264 281 29 -9999 -9999 -9999 2019 01 01 08 -62 -113 10268 268 39 -9999 -9999 -9999 2019 01 01 09 -59 -116 10271 254 31 3 -9999 -9999 2019 01 01 10 -62 -115 10271 238 24 -9999 -9999 -9999 2019 01 01 11 -80 -122 10269 254 12 -9999 -9999 -9999 2019 01 01 12 -67 -103 10264 322 12 5 -9999 -9999 2019 01 01 13 -62 -100 10261 27 13 -9999 -9999 -9999 2019 01 01 14 -29 -72 10259 230 40 -9999 -9999 -9999 2019 01 01 15 -20 -67 10254 242 49 5 -9999 -9999

字段解释如下:

字段1:位置1-4,长度4:观测年份,四舍五入到最接近 字段2:位置6-7,长度2:观察月,四舍五入到最接近 字段3:位置9-11,长度2:观察日,四舍五入到最接近 字段4:位置12-13,长度2:观察时,四舍五入到最接近 字段5:位置14-19,长度6:空气温度,单位:摄氏度,比例因子:10,缺少值:-9999, 字段6:位置20-24,长度6:露点温度,为了达到饱和,必须在恒定的压力和水蒸气含量下 冷却给定的空气包的温度。单位:摄氏度,比例因子:10,缺少值:-9999 字段7:Pos 26-31,长度6:海平面压力,相对于平均海平面的气压。单位:公顷,比例因 子:10,缺少值:-9999 字段8:32-37号位置,长度6:风向。正北角在正北和风向之间以顺时针方向测量的角度。 单位:角度。比例因子:1,缺少值:-9999。*注:静风风向编码为0。 字段9:38-43位置,长度6:风速,空气通过一个固定点的水平运动速度。单位:米每秒。 比例因子:10。缺少值:-9999 字段10:位置44-49,长度6:天空状况总覆盖代码,表示被云层或其它遮蔽现象覆盖的整个穹 顶的一部分的代码。缺少值:-9999 域: 0:无,SKC或CLR 1: 一个okta-1/10或更小但不是零 2: 两个oktas-2/10-3/10,或几个 3: 三个oktas-4/10 4: 四个oktas-5/10,或SCT 5: 五个oktas-6/10 6: 六个oktas-7/10-8/10 7: 七个oktas-9/10或以上,但不是10/10或BKN 8: 八个oktas-10/10,或OVC 9: 天空模糊不清,或云量无法估计 10: 部分遮蔽 11: 稀散 12: 分散的 13: 暗散射 14: 薄断 15: 破碎的 16: 暗断 17: 薄阴 18: 阴天 19: 阴天 字段11:位置50-55,长度6:液体沉淀深度尺寸-持续一小时,在一个小时的积累期内测量 的液体沉淀的深度。单位:毫米,比例因子:10,缺少值:-9999。*注:痕量降水编码为-1 字段12:位置56-61,长度6:液体沉淀深度尺寸-持续6小时,在六小时的积累期内测量的液 体沉淀的深度。单位:毫米。比例因子:10。缺少值:-9999。*注:痕量降水编码为-1

字段很多,但是这里我只用前5个字段,任务是统计每日最高温度、最低温度、平均温度,有时间的话顺便计算点儿静态统计值。其余字段应该是类似的,正所谓一通百通。

1.3 合并数据

数据很分散,合并数据: zcat 2019/*.gz > data.txt

到此数据获取完毕。

2 MapReduce处理数据 2.1 环境配置,启动集群

详情跳转到 : 大数据学习系列:Hadoop3.0苦命学习(一),本文不再赘述。

2.2 上传到HDFS hdfs dfs -mkdir -p /usr/hadoop/in hdfs dfs -ls /usr/hadoop/ hdfs dfs -put data.txt /usr/hadoop/in/

执行截图: 在这里插入图片描述 去控制台查看一下是否成功:

在这里插入图片描述

2.2 编写MapReduce代码 2.2.1 TemperatureMapper public class TemperatureMapper extends Mapper { private static final long MISSING = -9999; @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); Iterable split = Splitter.on(" ").omitEmptyStrings().split(line); ArrayList arrayList = new ArrayList(16); for (String s : split) { arrayList.add(s); } // 过滤掉字段不足的数据 if (arrayList.size() >= 5) { String month = arrayList.get(1); String day = arrayList.get(2); long temperature = Long.parseLong(arrayList.get(4)); // 过滤掉温度不存在的数据 if (Math.abs(temperature - MISSING) > 0.0001) { context.write(new Text(month + "/" + day), new LongWritable((temperature))); } } } }

主要是原数据进行了清洗,过滤了一些不合格的数据。

2.2.2 TemperatureReducer public class TemperatureReducer extends Reducer { @Override protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException { long maxTemperature = Long.MIN_VALUE; long minTemperature = Long.MAX_VALUE; double avgTemperature = 0.0; long temp; int count = 0; if (values!=null) { for (LongWritable value: values) { temp = value.get(); maxTemperature = Math.max(temp, maxTemperature); minTemperature = Math.min(temp, minTemperature); avgTemperature += temp; count++; } Temperature temperature = new Temperature(maxTemperature, minTemperature, avgTemperature/count); context.write(key, temperature); } } }

计算出每日温度的最大值、最小值和平均值,并放入Temperature对象中。

2.2.3 JobMain public class JobMain extends Configured implements Tool { @Override public int run(String[] strings) throws Exception { // 创建一个任务对象 Job job = Job.getInstance(super.getConf(), "mapreduce_temperature"); // 打包放在集群运行时,需要做一个配置 job.setJarByClass(JobMain.class); // 第一步:设置读取文件的类:K1和V1 job.setInputFormatClass(TextInputFormat.class); TextInputFormat.addInputPath(job, new Path("hdfs://node01:8020/usr/hadoop/in")); // 第二步:设置Mapper类 job.setMapperClass(TemperatureMapper.class); // 设置Map阶段的输出类型:k2和v2的类型 job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(LongWritable.class); // 第三、四、五、六步采用默认方式(分区,排序,规约,分组) // 第七步:设置Reducer类 job.setReducerClass(TemperatureReducer.class); // 设置Reduce阶段的输出类型 job.setOutputKeyClass(Text.class); job.setOutputValueClass(Temperature.class); // 第八步:设置输出类 job.setOutputFormatClass(TextOutputFormat.class); // 设置输出路径 TextOutputFormat.setOutputPath(job, new Path("hdfs://node01:8020/usr/hadoop/temperature")); boolean b = job.waitForCompletion(true); return b?0:1; } public static void main(String[] args) throws Exception { Configuration configuration = new Configuration(); // 启动一个任务 ToolRunner.run(configuration, new JobMain(), args); } } 2.3 执行 2.3.1 打包、上传

老套路,不说了。

2.3.2 运行

hadoop jar temperature_test-1.0-SNAPSHOT.jar cn.sky.hadoop.JobMain 执行结果: 在这里插入图片描述 在这里看一眼数据: 在这里插入图片描述 嗯,还行。

3 导入数据到Hive

Hive详情过程,请参考:大数据学习系列:Hadoop3.0苦命学习(五)

有个问题,若直接从HDFS导入数据到Hive,HDFS上的数据会丢失。

所以我将数据下载下来,重命名为 temperature_data ,并上传到 node03 上 在这里插入图片描述 数据有了,开始创建Hive表:

create external table temperature (t_date string, t_max double, t_min double, t_avg double) row format delimited fields terminated by '\t';

加载数据到hive:

load data local inpath '/export/services/temperature_data' overwrite into table temperature;

查前面5条数据,看一眼:

select * from temperature limit 5;

在这里插入图片描述

4 Hive数据分析

弄得简单,就查几个静态数据吧。

查询2019全年平均温度 select avg(t_avg) from temperature;

哇,太慢了,查了25秒,最终结果是3.46(因为数据是被放大了10倍)左右 在这里插入图片描述

查询2019全年高于平均温度的天数 select count(1) from temperature where t_avg > 34.6; 答案是:196天,很显然低于平均气温的天数是169天。

在这里插入图片描述 好了,差不多就行了。

5 使用Sqoop导入数据到Mysql

Sqoop详情过程,请参考:大数据学习系列:Hadoop3.0苦命学习(七)

5.1 Mysql创建数据库 CREATE TABLE `temperature` ( `Tem_Date` varchar(10) NOT NULL, `Tem_Max` double DEFAULT NULL, `Tem_Min` double DEFAULT NULL, `Tem_Avg` double DEFAULT NULL, PRIMARY KEY (`Tem_Date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 5.2 开始导入 bin/sqoop export --connect jdbc:mysql://192.168.0.102:3306/userdb --username root --password 123456 --table temperature --export-dir /usr/hadoop/temperature --input-fields-terminated-by "\t"

经过半分钟的等待,就可以在mysql中查到数据了,见下图: 在这里插入图片描述 不错,数据很好。

6 展示数据

这里前端使用echart,jsp,后端使用Spring、SpringMVC、Mybatis。

代码较多,展示主要的。

6.1 前端代码

在这里插入图片描述 主要是这一段,使用Ajax向后台请求数据,然后将数据丢进eChart中。

6.2 后端代码

controller层

@Autowired private TemperatureService tempService; @RequestMapping("/getTemperature.action") @ResponseBody public TemperatureReturnPojo getTemperature(){ TemperatureReturnPojo temperaturePojo = tempService.getAllTemperature(); System.out.println(temperaturePojo); return temperaturePojo; }

Service层

public interface TemperatureService { TemperatureReturnPojo getAllTemperature(); }

Service实现类

@Service public class TemperatureServiceImpl implements TemperatureService { @Autowired private TemperatureMapper temperatureMapper; @Override public TemperatureReturnPojo getAllTemperature() { TemperatureReturnPojo temperatureReturnPojo = new TemperatureReturnPojo(); ArrayList dates = new ArrayList(); ArrayList maxs = new ArrayList(); ArrayList mins = new ArrayList(); ArrayList avgs = new ArrayList(); DecimalFormat df = new DecimalFormat("#.00"); List allTemperature = temperatureMapper.getAllTemperature(); for (TemperaturePojo pojo : allTemperature) { dates.add(pojo.getTem_Date()); maxs.add(df.format(pojo.getTem_Max()/10.0)); mins.add(df.format(pojo.getTem_Min()/10.0)); avgs.add(df.format(pojo.getTem_Avg()/10.0)); } temperatureReturnPojo.setTem_Dates(dates); temperatureReturnPojo.setTem_Maxs(maxs); temperatureReturnPojo.setTem_Mins(mins); temperatureReturnPojo.setTem_Avgs(avgs); return temperatureReturnPojo; } }

实体类

public class TemperaturePojo { private String Tem_Date; private Double Tem_Max; private Double Tem_Min; private Double Tem_Avg; // 省略Get()、Set()、ToString()方法 } public class TemperatureReturnPojo { private List Tem_Dates; private List Tem_Maxs; private List Tem_Mins; private List Tem_Avgs; // 省略Get()、Set()、ToString()方法 }

Mapper

public interface TemperatureMapper { List getAllTemperature(); } select * from temperature;

运行结果如下: 在这里插入图片描述 在这里插入图片描述 流程完成,撒花~~~

代码:完整代码下载

csdn资源下载从1积分涨到了50积分,可怕。

因此我又把放到了github 完整代码下载

2022年12月15日更新:很多同学在问数据在哪在哪,其实在1.1节已经说过了,现在说详细点儿。

linux命令行输入:

wget -D --accept-regex=REGEX -P data -r -c ftp://ftp.ncdc.noaa.gov/pub/data/noaa/isd-lite/2019/5*

就会看到下面的提示,表示正在下载了。 在这里插入图片描述

下载一会儿后,当前目录下就会有 data/ftp.ncdc.noaa.gov/pub/data/noaa/isd-lite/2019 ,进入这个目录,你可以看到1.1节的数据了。

在这里插入图片描述



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有